﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using QuestFramework;
using QuestFramework.UI;
using QuestFramework.Debug;

namespace QuestFramework
{
    public class Cube
    {
        private float lineLength;
        private VertexPositionColor[] cubeVertices;
        private BasicEffect effect;
        private Camera camera;
        private Color cubeColor;
        private bool isMoving;
        private bool isMovingLeft;
        private bool isMovingUp;
        private int moveSpeed;
        private float targetX;
        private float totalX;
        private float targetZ;
        private float totalZ;

        public Cube()
        {
            camera = Camera.Instance;
        }

        public Cube(float length, Color color) : this()
        {
            lineLength = length;
            cubeColor = color;
            isMoving = false;
            moveSpeed = 1;
        }

        public void Initialize(GraphicsDevice graphicsDevice)
        {
            CreateVertices();
            CreateEffect(graphicsDevice);
        }

        public void MoveAcrossX(int numberOfTiles)
        {
            if (!isMoving)
            {
                isMoving = true;
                if (numberOfTiles < 0)
                    isMovingLeft = true;
                else
                    isMovingLeft = false;

                targetX = (numberOfTiles * 1000);
            }
        }

        public void MoveAcrossZ(int numberOfTiles)
        {
            if (!isMoving)
            {
                isMoving = true;
                if (numberOfTiles < 0)
                    isMovingUp = true;
                else
                    isMovingUp = false;

                targetZ = (numberOfTiles * 1000);
            }
        }

        private void CreateVertices()
        {
            List<VertexPositionColor> tempVertices = new List<VertexPositionColor>();
            Vector3 currentPosition = new Vector3(0f, 0f, 0f);
            currentPosition.X = lineLength / 2;
            currentPosition.Z = lineLength / 2;
            currentPosition.Y = lineLength;

            VertexPositionColor topBackLeftVertex = new VertexPositionColor(currentPosition, cubeColor);
            VertexPositionColor topBackRightVertex = new VertexPositionColor(currentPosition + new Vector3(lineLength, 0, 0), cubeColor);
            VertexPositionColor topFrontLeftVertex = new VertexPositionColor(currentPosition + new Vector3(0, 0, lineLength), cubeColor);
            VertexPositionColor topFrontRightVertex = new VertexPositionColor(currentPosition + new Vector3(lineLength, 0, lineLength), cubeColor);
            VertexPositionColor bottomBackLeftVertex = new VertexPositionColor(topBackLeftVertex.Position - new Vector3(0, lineLength, 0), cubeColor);
            VertexPositionColor bottomBackRightVertex = new VertexPositionColor(topBackRightVertex.Position - new Vector3(0, lineLength, 0), cubeColor);
            VertexPositionColor bottomFrontLeftVertex = new VertexPositionColor(topFrontLeftVertex.Position - new Vector3(0, lineLength, 0), cubeColor);
            VertexPositionColor bottomFrontRightVertex = new VertexPositionColor(topFrontRightVertex.Position - new Vector3(0, lineLength, 0), cubeColor);

            // Top Face
            tempVertices.Add(topBackLeftVertex);
            tempVertices.Add(topBackRightVertex);
            tempVertices.Add(topFrontRightVertex);
            tempVertices.Add(topFrontRightVertex);
            tempVertices.Add(topFrontLeftVertex);
            tempVertices.Add(topBackLeftVertex);

            // Back Face
            tempVertices.Add(topBackRightVertex);
            tempVertices.Add(topBackLeftVertex);
            tempVertices.Add(bottomBackRightVertex);
            tempVertices.Add(bottomBackRightVertex);
            tempVertices.Add(topBackLeftVertex);
            tempVertices.Add(bottomBackLeftVertex);

            // Left Face
            tempVertices.Add(topBackLeftVertex);
            tempVertices.Add(topFrontLeftVertex);
            tempVertices.Add(bottomFrontLeftVertex);
            tempVertices.Add(topBackLeftVertex);
            tempVertices.Add(bottomFrontLeftVertex);
            tempVertices.Add(bottomBackLeftVertex);

            // Right Face
            tempVertices.Add(topFrontRightVertex);
            tempVertices.Add(topBackRightVertex);
            tempVertices.Add(bottomBackRightVertex);
            tempVertices.Add(bottomBackRightVertex);
            tempVertices.Add(bottomFrontRightVertex);
            tempVertices.Add(topFrontRightVertex);

            // Front Face
            tempVertices.Add(topFrontLeftVertex);
            tempVertices.Add(topFrontRightVertex);
            tempVertices.Add(bottomFrontRightVertex);
            tempVertices.Add(topFrontLeftVertex);
            tempVertices.Add(bottomFrontRightVertex);
            tempVertices.Add(bottomFrontLeftVertex);

            // Bottom Face
            tempVertices.Add(bottomFrontRightVertex);
            tempVertices.Add(bottomBackRightVertex);
            tempVertices.Add(bottomBackLeftVertex);
            tempVertices.Add(bottomBackLeftVertex);
            tempVertices.Add(bottomFrontLeftVertex);
            tempVertices.Add(bottomFrontRightVertex);

            //tempVertices.Add();

            cubeVertices = tempVertices.ToArray();
        }

        private void CreateEffect(GraphicsDevice graphicsDevice)
        {
            effect = new BasicEffect(graphicsDevice);
            effect.TextureEnabled = false;
            effect.LightingEnabled = false;
            effect.VertexColorEnabled = true;
        }

        public void Update()
        {
            if (isMoving)
            {
                int horizontalMoveDirection;
                if (targetX != 0)
                {
                    if (isMovingLeft)
                        horizontalMoveDirection = -1;
                    else
                        horizontalMoveDirection = 1;
                }
                else
                    horizontalMoveDirection = 0;

                int depthMoveDirection;
                if (targetZ != 0)
                {
                    if (isMovingUp)
                        depthMoveDirection = -1;
                    else
                        depthMoveDirection = 1;
                }
                else
                    depthMoveDirection = 0;

                for (int vertexIndex = 0; vertexIndex < cubeVertices.Count(); vertexIndex++)
                {
                    cubeVertices[vertexIndex].Position.X += horizontalMoveDirection * moveSpeed;
                    cubeVertices[vertexIndex].Position.Z += depthMoveDirection * moveSpeed;
                }

                totalX += horizontalMoveDirection;
                totalZ += depthMoveDirection;

                if (totalX == targetX && targetX != 0)
                {
                    isMoving = false;
                    totalX = 0;
                    targetX = 0;
                }

                if (totalZ == targetZ && targetZ != 0)
                {
                    isMoving = false;
                    totalZ = 0;
                    targetZ = 0;
                }
            }
        }

        public void Draw(GraphicsDevice graphicsDevice)
        {
            //effect.World = camera.World;
            effect.View = camera.View;
            effect.Projection = camera.Projection;

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();

                graphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleList
                    , cubeVertices, 0, 12, VertexPositionColor.VertexDeclaration);
            }
        }
    }
}
